package com.dycx.api.controller.app.cms;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dycx.cms.converter.ArticleConverter;
import com.dycx.cms.dto.ArticleDTO;
import com.dycx.cms.entity.ArticleDO;
import com.dycx.cms.service.ArticleService;
import com.dycx.cms.service.ArticleTypeService;
import com.dycx.cms.vo.ArticleTypeVO;
import com.dycx.cms.vo.ArticleVO;
import com.dycx.common.RestResponse;
import com.dycx.common.annotation.Authorization;
import com.dycx.common.context.UserInfoContext;
import com.dycx.common.enums.BizTypeEnum;
import com.dycx.system.service.ConfigService;
import com.dycx.system.vo.SystemConfig;
import com.dycx.user.entity.ReadLogDO;
import com.dycx.user.entity.UserInfoDO;
import com.dycx.user.enums.VipGradeEnum;
import com.dycx.user.service.ReadLogService;
import com.dycx.user.service.UserAuthService;
import com.dycx.user.service.UserInfoService;
import com.dycx.user.service.UserService;
import com.dycx.user.vo.UserVO;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@RestController
@RequestMapping(value = "/app/cms/article")
@AllArgsConstructor
public class ArticleApiController {

    private ArticleService articleService;
    private ArticleTypeService articleTypeService;
    private ReadLogService readLogService;
    private UserService userService;
    private UserInfoService userInfoService;
    private UserAuthService userAuthService;
    private ConfigService configService;

    /**
     * 分页
     **/
    @PostMapping("/getPage")
    public RestResponse<Page<ArticleVO>> getPage(@RequestBody ArticleDTO articleDto, HttpServletRequest request) {
        String token = request.getHeader("authorization");
        UserVO userVO = userAuthService.getTokenInfo(token);
        articleDto.setStatus(true);
        articleDto.setOrderBy("update_time desc");
        Page<ArticleVO> page = articleService.getPage(articleDto);
        page.setRecords(articleService.setAppData(page.getRecords(), userVO));

        return RestResponse.success(page);
    }

    /**
     * 获取未发布文章
     **/
    @Authorization
    @PostMapping("/getUnpublishPage")
    public RestResponse<Page<ArticleVO>> getUnpublishPage(@RequestBody ArticleDTO articleDto) {
        UserVO userVO = userService.load(UserInfoContext.get().getUserId());
        if (ObjectUtil.isNull(userVO) || ObjectUtil.isNull(userVO.getAdminId()) || userVO.getAdminId() == 0) {
            throw new RuntimeException("没有操作权限");
        }
        articleDto.setStatus(false);
        Page<ArticleVO> page = articleService.getPage(articleDto);
        return RestResponse.success(page);
    }


    /**
     * 查询详细
     **/
    @PostMapping("/load")
    public RestResponse<ArticleVO> load(@RequestBody ArticleDTO articleDto, HttpServletRequest request) {
        String token = request.getHeader("authorization");
        UserVO userVO = userAuthService.getTokenInfo(token);

        if (ObjectUtil.isNull(userVO) || ObjectUtil.isNull(userVO.getAdminId()) || userVO.getAdminId() == 0) {
            articleDto.setStatus(true);
        }

        ArticleVO articleVO = articleService.getDetailById(articleDto.getId(), articleDto.getStatus());
        Assert.notNull(articleVO, "未查询到数据");

        List<ArticleVO> articleList = new ArrayList<>();
        articleList.add(articleVO);

        articleList = articleService.setAppData(articleList, userVO);

        return RestResponse.success(articleList.get(0));
    }

    /**
     * 获取子分类
     **/
    @GetMapping("/getChildType")
    public RestResponse<List<ArticleTypeVO>> getChildType(Integer parentId) {
        return RestResponse.success(articleTypeService.getListByParentId(parentId, true));
    }

    /**
     * 获取子分类并统计未发布文章数
     **/
    @GetMapping("/getChildTypeCount")
    public RestResponse<List<ArticleTypeVO>> getChildTypeCount(Integer parentId) {
        List<ArticleTypeVO> typeList = articleTypeService.getListByParentId(parentId, true);
        for (ArticleTypeVO vo : typeList) {
            LambdaQueryWrapper<ArticleDO> lambda = new LambdaQueryWrapper<>();
            lambda.eq(ArticleDO::getArticleTypeId, vo.getId());
            lambda.eq(ArticleDO::getStatus, false);
            vo.setArticleTypeName(vo.getArticleTypeName() + "-" + articleService.count(lambda));
        }
        return RestResponse.success(typeList);
    }

    /**
     * 添加
     **/
    @Authorization
    @PostMapping("/add")
    public RestResponse<?> add(@RequestBody @Valid ArticleDTO articleDto) {
        UserVO userVO = userService.load(UserInfoContext.get().getUserId());
        if (ObjectUtil.isNull(userVO.getAdminId()) || userVO.getAdminId() < 1) {
            return RestResponse.fail("没有操作权限");
        }
        return articleService.add(articleDto) ? RestResponse.success() : RestResponse.fail();
    }

    /**
     * 修改
     **/
    @Authorization
    @PostMapping("/edit")
    public RestResponse<?> edit(@RequestBody @Valid ArticleDTO articleDto) {
        UserVO userVO = userService.load(UserInfoContext.get().getUserId());
        if (ObjectUtil.isNull(userVO.getAdminId()) || userVO.getAdminId() < 1) {
            return RestResponse.fail("没有操作权限");
        }

        return articleService.edit(articleDto) ? RestResponse.success() : RestResponse.fail();
    }

    /**
     * 添加
     **/
    @Authorization
    @GetMapping("/addReadLog")
    public RestResponse<Boolean> addReadLog(Integer id) {
        UserVO userVO = userService.load(UserInfoContext.get().getUserId());
        //同一条数据一天不限下载次数
        LambdaQueryWrapper<ReadLogDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ReadLogDO::getUid, UserInfoContext.get().getUserId());
        wrapper.eq(ReadLogDO::getBizType, BizTypeEnum.CMS_ARTICLE.getCode());
        wrapper.eq(ReadLogDO::getBizId, id);
        wrapper.ge(ReadLogDO::getCreateTime, LocalDateTimeUtil.beginOfDay(LocalDateTime.now()));
        wrapper.le(ReadLogDO::getCreateTime, LocalDateTimeUtil.endOfDay(LocalDateTime.now()));
        if (ObjectUtil.isNotEmpty(readLogService.getOne(wrapper)))
            return RestResponse.message(-4, "", true);

        if (ObjectUtil.isNotEmpty(userVO.getTryNum()) && userVO.getTryNum() > 0) {
            UserInfoDO userInfoDO = new UserInfoDO();
            userInfoDO.setUid(userVO.getUid());
            userInfoDO.setTryNum(userVO.getTryNum() - 1);
            if (!userInfoService.edit(userInfoDO)) return RestResponse.fail("试用更新失败");

            //加入日志
            ReadLogDO readLogDO = new ReadLogDO();
            readLogDO.setUid(UserInfoContext.get().getUserId());
            readLogDO.setBizType(BizTypeEnum.CMS_ARTICLE.getCode());
            readLogDO.setBizId(id);
            if (!readLogService.save(readLogDO)) return RestResponse.fail("查询失败");

            return RestResponse.message(-4, "", true);
        }

        if (userVO.getVipGrade() < VipGradeEnum.BRONZE.getCode())
            return RestResponse.message(-4, "升级为VIP，获取优质文案", false);

        //无限下载
        Integer downloadNum = VipGradeEnum.converter(userVO.getVipGrade()).getDownloadNum();
        if (downloadNum == -1) return RestResponse.message(-4, "", true);

        //是否超过当天最大下载次数
        LambdaQueryWrapper<ReadLogDO> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(ReadLogDO::getUid, UserInfoContext.get().getUserId());
        wrapper2.ge(ReadLogDO::getCreateTime, LocalDateTimeUtil.beginOfDay(LocalDateTime.now()));
        wrapper2.le(ReadLogDO::getCreateTime, LocalDateTimeUtil.endOfDay(LocalDateTime.now()));
        if (readLogService.count(wrapper2) >= downloadNum) {
            return RestResponse.message(-4, "今日下载次数已用完，去升级提升下载次数？", false);
        }

        //加入日志
        ReadLogDO readLogDO = new ReadLogDO();
        readLogDO.setUid(UserInfoContext.get().getUserId());
        readLogDO.setBizType(BizTypeEnum.CMS_ARTICLE.getCode());
        readLogDO.setBizId(id);
        if (!readLogService.save(readLogDO)) return RestResponse.fail("查询失败");

        return RestResponse.message(-4, "", true);
    }

    /**
     * 自动发布
     */
    @GetMapping("/autoPublish")
    public RestResponse<String> autoPublish() {
        int h = LocalDateTime.now().getHour();


        if (h != 7 && h != 17) {
            return RestResponse.fail();
        }

        SystemConfig config = configService.getSystemConfig();
        String num = "1";
        if (h == 7) {
            num = config.getArticleMorningPublishNum();
        }
        if (h == 17) {
            num = config.getArticleEveningPublishNum();
        }

        List<ArticleTypeVO> typeList = articleTypeService.getAllList(69, true);

        for (ArticleTypeVO item : typeList) {
            LambdaQueryWrapper<ArticleDO> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ArticleDO::getArticleTypeId, item.getId());
            wrapper.eq(ArticleDO::getStatus, false);
            wrapper.orderByAsc(ArticleDO::getHits);
            wrapper.select(ArticleDO::getId, ArticleDO::getStatus);
            wrapper.last("limit " + num);
            List<ArticleDO> articleList = articleService.list(wrapper);
            articleList.forEach(article -> {
                article.setStatus(true);
                articleService.updateById(article);
            });
        }


        return RestResponse.success();
    }

    /**
     * 检测内容是否重复
     *
     * @param dto
     * @return
     */
    @PostMapping("/detectionRepeat")
    public RestResponse<Map<String, Object>> detectionRepeat(@RequestBody ArticleDTO dto) {
        String[] arr = dto.getSummary().split("\n");
        if (arr.length < 2) {
            String str = dto.getSummary().replace(",", "|")
                    .replace("\n\n\n\n", "\n")
                    .replace("\n\n\n", "\n")
                    .replace("\n\n", "\n")
                    .replace("，", "|")
                    .replace(".", "|")
                    .replace("。", "|")
                    .replace(";", "|")
                    .replace("；", "|")
                    .replace("?", "|")
                    .replace("？", "|")
                    .replace("、", "|")
                    .replace(" ", "|")
                    .replace("　", "|");
            arr = str.split("\\|");
        }

        List<ArticleVO> articleList = new ArrayList<>();
        List<Integer> ids = new ArrayList<>();
        int totalNum = 0;
        int equalNum = 0;
        for (String s : arr) {
            if (s.length() > 4) {
                totalNum++;
                LambdaQueryWrapper<ArticleDO> lambda = new LambdaQueryWrapper();
                lambda.like(ArticleDO::getSummary, s);
                lambda.select(ArticleDO::getId, ArticleDO::getSummary);
                lambda.ne(ObjectUtil.isNotNull(dto.getId()), ArticleDO::getId, dto.getId());
                lambda.last("limit 1");

                ArticleDO articleDO = articleService.getOne(lambda);
                if (ObjectUtil.isNotEmpty(articleDO)) {
                    if(!ids.contains(articleDO.getId())){
                        articleList.add(ArticleConverter.entityToVo(articleDO));
                        ids.add(articleDO.getId());
                    }
                    equalNum++;
                }
            }
        }

        Map<String, Object> map = new HashMap<>();

        if (equalNum > 0) {
            map.put("list", articleList);
            map.put("rate", equalNum * 100 / totalNum);
            return RestResponse.message(-4, "fail", map);
        } else {
            return RestResponse.message(-4, "success", map);
        }
    }
}
